package com.guchenbo.example.juc;

import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

/**
 * @Author guchenbo
 * @Date 2018/10/30.
 */
public class CountDownLatchDemo {

    public static void main(String[] args) throws InterruptedException {
        CountDownLatchDemo demo = new CountDownLatchDemo();
        //        demo.test();
//        demo.test2();
        demo.test3();
    }

    public void test() {
        int count = 5;
        CountDownLatch work = new CountDownLatch(count);
        ExecutorService executor = Executors.newFixedThreadPool(3);
        Worker task = new Worker(null, work);

        IntStream.range(0, count).forEach(i -> executor.submit(task));
        try {
            work.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("all work done!");
        ExecutorUtils.stop(executor, 5);
    }

    public void test2() {
        int count = 5;
        CountDownLatch start = new CountDownLatch(1);
        CountDownLatch work = new CountDownLatch(count);
        ExecutorService executor = Executors.newFixedThreadPool(10);
        Worker task = new Worker(start, work);

        IntStream.range(0, count).forEach(i -> executor.submit(task));
        try {
            System.out.println("all work start");
            start.countDown();
            work.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("all work done!");
        ExecutorUtils.stop(executor, 5);
    }

    /**
     * 所有work同时开始
     */
    public void test3() throws InterruptedException {
        int count = 5;
        CountDownLatch start = new CountDownLatch(1);
        ExecutorService executor = Executors.newFixedThreadPool(10);
        Worker task = new Worker(start, null);

        IntStream.range(0, count).forEach(i -> executor.submit(task));
        Thread.sleep(5000);
        start.countDown();
        System.out.println("all work start");
//        ExecutorUtils.stop(executor, 5);
    }

    class Worker implements Runnable {
        private CountDownLatch start;
        private CountDownLatch work;

        public Worker(CountDownLatch start, CountDownLatch work) {
            this.start = start;
            this.work = work;
        }

        @Override
        public void run() {
            if (start != null) {
                try {
                    start.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("start work " + Thread.currentThread().getName());
            try {
                TimeUnit.SECONDS.sleep(new Random().nextInt(3));
            } catch (InterruptedException e) {
                System.out.println("interrupt work " + Thread.currentThread().getName());
            } finally {
                if (work != null) {
                    work.countDown();
                }
                try {
                    TimeUnit.SECONDS.sleep(new Random().nextInt(3));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("done work " + Thread.currentThread().getName());
            }
        }
    }
}
